﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Caching;
using System.Web.Caching;
using System.Web;

namespace common
{
    public class EventCache<T> : EventArgs
    {
        internal EventCache(string key, T value)
            : base()
        {
            Key = key;
            Value = value;
        }
        public string Key;
        public T Value;

    }
    public class CacheSystem<T>
    {
        private static MemoryCache mc;
        private static Cache httpCache;
        private CacheEntryRemovedCallback removedEntry;
        private CacheItemRemovedCallback removedItem;
        public event EventHandler<EventCache<T>> removedFromCache;//TODO : make what is removed!
        public CacheSystem()
        {
            if (HttpContext.Current != null && HttpContext.Current.Cache != null)
            {
                httpCache = HttpContext.Current.Cache;
                removedItem = new CacheItemRemovedCallback(ItemRemovedCallback);
            }
            else
            {
                mc = MemoryCache.Default;
                removedEntry = new CacheEntryRemovedCallback(EntryRemovedCallback);
            }


        }
        public void AddCache(string key, T value, int Minutes)
        {
            TimeSpan ts = new TimeSpan(0, Minutes, 0);
            if (mc != null)
            {
                CacheItemPolicy cp = new CacheItemPolicy();
                cp.SlidingExpiration = ts;
                cp.RemovedCallback = removedEntry;
                cp.Priority = System.Runtime.Caching.CacheItemPriority.Default;                
                mc.Add(key, value, cp);
            }
            else
            {
                httpCache.Add(key, value, null, Cache.NoAbsoluteExpiration, ts, System.Web.Caching.CacheItemPriority.Default, removedItem);
            }



        }
        public T GetValue(string Key)
        {
            try
            {
                if (mc != null)
                {

                    return (T)mc.Get(Key);

                }
                else
                {
                    return (T)httpCache.Get(Key);
                }
            }
            catch (Exception ex)
            {
                //TODO: log exception
                return default(T);
            }
        }
        
        public void RemoveCache(string Key)
        {
            if (mc != null)
            {
                mc.Remove(Key);
            }
            else
            {
                httpCache.Remove(Key);
            }
        }
        private void EntryRemovedCallback(CacheEntryRemovedArguments arguments)
        {
            if (removedFromCache != null)
            {
                string key = arguments.CacheItem.Key;
                T value = (T)arguments.CacheItem.Value;
                removedFromCache(this, new EventCache<T>(key, value));
            }
        }
        private void ItemRemovedCallback(string key, object value, CacheItemRemovedReason reason)
        {
            if (removedFromCache != null)
            {
                removedFromCache(this, new EventCache<T>(key, (T)value));
            }
        }
    }
}
